package edu.chalmers.AV_2DPlatformerFramework.Model;

/**
 * Abstract superclass for classes specifying interaction layers for {@code
 * GameObject}s.
 * @version 1.0
 * @author Gustav Vidhög
 */
public abstract class Layer {
    
    /**
     * Method specifying whether this {@code Layer} interacts with another.
     * {@code Layer}s of the {@code NEGATIVE} interaction class do not interact
     * with any {@code Layer}s, including themselves, those of the {@code
     * UNIVERSAL} class interact with all {@code Layer}s other than those in the
     * {@code NEGATIVE}  class, and those in the {@code CONDITIONAL} class
     * interact only with its own {@code Layer} and those of the {@code
     * UNIVERSAL} class.
     * @param layer - the {@code Layer} to test whether this {@code Layer}
     * interacts with.
     * @return {@code true} if this {@code Layer} interacts with {@code layer};
     * {@code false} otherwise.
     * @author Gustav Vidhög
     * @version 1.0
     * @since 1.0
     */
    public final boolean interactsWith (Layer layer) {
        if (layer == null ||
                layer.getInteractionClass() == InteractionClass.NEGATIVE ||
                this.getInteractionClass() == InteractionClass.NEGATIVE) {
            return false;
        } else if (layer.getInteractionClass() == InteractionClass.UNIVERSAL ||
                this.getInteractionClass() == InteractionClass.UNIVERSAL) {
            return true;
        } else {
            return (this.getClass() == layer.getClass());
        }
    }
    
    /**
     * Method specifying the interaction class for this {@code Layer}.
     * @return interaction class for this {@code Layer}.
     * @author Gustav Vidhög
     * @version 1.0
     * @since 1.0
     */
    protected abstract InteractionClass getInteractionClass ();
    
    /**
     * Creates and returns a deep copy of this {@code Layer}. For any
     * {@code Layer} {@code l}, the expression:
     * <blockquote>
     * <pre>
     * l.copy() != l</pre></blockquote>
     * and the expression:
     * <blockquote>
     * <pre>
     * x.copy().equals(x)</pre></blockquote>
     * are both {@code true}.
     * @return a deep copy of this {@code Layer}.
     * @author Gustav Vidhög
     * @version 1.0
     * @since 1.0
     */
    public abstract Layer copy();
    
    /**
     * Indicates whether some other object is "equal to" this {@code Layer}.
     * @param obj - the reference {@code Object} with which to compare.
     * @return {@code true} if this {@code Layer} is the same as the {@code obj}
     * argument; {@code false} otherwise.
     * @author Gustav Vidhög
     * @version 1.0
     * @since 1.0
     */
    @Override
    public abstract boolean equals(Object obj);
    
    /**
     * Returns a hash code value for the {@code Layer}.
     * @return a hash code value for this {@code Layer}.
     * @author Gustav Vidhög
     * @version 1.0
     * @since 1.0
     */
    @Override
    public abstract int hashCode();
    
    /**
     * Type enumerating the classes of {@code Layer}s, divided by interactivity.
     * @author Gustav Vidhög
     * @version 1.0
     * @since 1.0
     */
    public enum InteractionClass {
        UNIVERSAL, CONDITIONAL, NEGATIVE
    }
}
